/**
* @file ALErrorChecker.cpp
* @author Max Ocklind
* @version 2010-01-11
*
* A small helper class to check for silent errors raised by OpenAL during runtime.</br>
* The function <code>throwError</code> also alows for throwing user specified error strings.
**/


/* includes */

#include "ALErrorChecker.h"


// initate singleton
ALErrorChecker* sm = new ALErrorChecker;


/* Error checking functions */

/**
* Checks and resets the AL error state of OpenAL, and throws an exception if an AL error occured.
*
* @param who a string describing in what class or instance of a class the error occured
* @param when a string describing when the error occurred (preferably including the function name)
* @throws string a string describing the AL error that occured
*/
void ALErrorChecker::checkALError(const char* who, const char* when)
{
	ALenum error = alGetError();
	if (error != AL_NO_ERROR)
		if (AL_DEBUG)
			printf("AL %s error: %s (%s)\n", when, alGetString(error), who);
		else
			throwError("AL", who, when, alGetString(error));
}

/**
* Checks and resets the ALC error state of OpenAL, and throws an exception if an ALC error occured.
*
* @param who a string describing in what class or instance of a class the error occured
* @param when a string describing when the error occurred (preferably including the function name)
* @throws string a string describing the ALC error that occured
*/
void ALErrorChecker::checkALCError(const char* who, const char* when)
{
	ALCcontext* context = alcGetCurrentContext();
	ALCdevice*  device  = alcGetContextsDevice(context);

	ALCenum error = alcGetError(device);
	if (error != ALC_NO_ERROR)
		if (AL_DEBUG)
			printf("ALC %s error: %s (%s)\n", when, alcGetString(device, error), who);
		else
			throwError("ALC", who, when, alcGetString(device, error));
}

/**
* Checks and resets the ALUT error state of OpenAL, and throws an ALUT exception if an error occured.
*
* @param who a string describing in what class or instance of a class the error occured
* @param when a string describing when the error occurred (preferably including the function name)
* @throws string a string describing the ALUT error that occured
*/
void ALErrorChecker::checkALUTError(const char* who, const char* when)
{
	ALenum error = alutGetError(); 
	if (error != ALUT_ERROR_NO_ERROR)
		if (AL_DEBUG)
			printf("ALUT %s error: %s (%s)\n", when, alutGetErrorString(error), who);
		else
			throwError("ALUT", who, when, alutGetErrorString(error));
}

/**
* Throws an exception with the specified parameters.
*
* @param errType a string description of the error type
* @param who a string describing in what class or instance of a class the error occured
* @param when a string describing when the error occurred (preferably including the function name)
* @param errString a string describing the error
* @throws string a string describing the error that occured
*/
void ALErrorChecker::throwError(const char* errType, const char* who, const char* when, const char* errString)
{
	std::stringstream ss;
	ss << errType << " " << when << " error: "  << errString << " (" << who << ")" << std::endl;

	if (AL_DEBUG)
		printf(ss.str().c_str());
	else
		throw ss.str();
}